#pragma once
#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
// #define Mydef 1

const std::string blank_space_sep = " ";
const std::string protocol_sep = "\n";

// 加装报头 abc --> 3"\n"abc"\n"
std::string Encode(std::string &connect)
{
    std::string package = std::to_string(connect.size());
    package += protocol_sep;
    package += connect;
    package += protocol_sep;
    return package;
}

// 提取有效载荷  3"\n"abc"\n" --> abc  
// 返回类型为bool, 因为传进来的报文不一定是遵循上面Encode协议来序列化的
bool Decode(std::string &package, std::string *content)
{
    std::size_t pos = package.find(protocol_sep);
    if (pos == std::string::npos)  return false;
    std::string len_str = package.substr(0, pos);
    // package = len_str + content_str + 2
    std::size_t len = std::stoi(len_str);
    std::size_t total_len = len + len_str.size() + 2;
    if (package.size() < total_len)  return false;

    *content = package.substr(pos+1, len);
    // package可能存在多个报文
    // 拿完一个报文就清除该报文的数据
    package.erase(0, total_len);
    return true;
}

class Request
{
public:
    Request() {}
    Request(int data1, int data2, char oper) :x(data1), y(data2), op(oper) 
    {}
    ~Request() {}
public:
    // 序列化
    bool Serialize(std::string *out)
    {
#ifdef Mydef
        // 构建报文的有效载荷  --> "x op y"
        std::string s = std::to_string(x);
        s += blank_space_sep;
        s += op;
        s += blank_space_sep;
        s += std::to_string(y);
        *out = s;
        return true;
#else
        Json::Value root;
        root["x"] = x;
        root["y"] = y;
        root["op"] = op;
        root["desc"] = std::to_string(x) + op + std::to_string(y);
        Json::StyledWriter w;
        // Json::FastWriter w;
        *out = w.write(root);
        // Debug
        std::cout << "Debug json:\n" << *out << std::endl;
        return true;
#endif
    }
    // 反序列化
    bool Deserialize(const std::string &in)
    {
#ifdef Mydef
        std::size_t left = in.find(blank_space_sep);
        if (left == std::string::npos)  return false;

        std::size_t right = in.rfind(blank_space_sep);
        if (right == std::string::npos)  return false;

        if (left + 2 != right) return false;
        
        x = std::stoi(in.substr(0, left));
        op = in[left+1];
        y = std::stoi(in.substr(right+1));
        return true;
#else
        Json::Value root;
        Json::Reader r;
        r.parse(in, root);
        x = root["x"].asInt();
        y = root["y"].asInt();
        op = root["op"].asInt();
        return true;
#endif
    }
    void DebugPrint()
    {
        std::cout << "Request done,  " << x << " " << op << " " << y; 
    }
public:
    // x op y
    int x;
    int y;
    char op;  // + - * / %
};



class Response
{
public:
    Response(){}
    Response(int res, int cd) :result(res), code(cd) 
    {}
    ~Response(){}
public:
    void Serialize(std::string *out)
    {
        // 构建报文的有效载荷 --> "result code"
        std::string s = std::to_string(result);
        s += blank_space_sep;
        s += std::to_string(code);
        *out = s;
    }
    bool Deserialize(std::string &in)
    {
        std::size_t pos = in.find(blank_space_sep);
        if (pos == std::string::npos)  return false;
        result = std::stoi(in.substr(0,pos));
        code = std::stoi(in.substr(pos+1));
        return true;
    }
    void DebugPrint()
    {
        std::cout << "Response done, result: " << result << " code: " << code << std::endl;
    }
public:
    int result;
    int code;  // 0,表示result结果可信
};